package pos.MessageBox;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.media.j3d.*;
import javax.vecmath.*;
import pos.IModeController;
import pos.utils.*;

/**
 *
 * @author plus
 */
public class MessageBox extends BranchGroup implements IContainer, Invokeable {
    private static final int STATUE_FIXED=0, STATUE_IN=1, STATUE_OUT=2;
    private int statue=STATUE_IN;
    private double step=0;
    private String currentEvent;
    private IModeController myController,  receiver;
    private String title,  contect;
    private String[] buttonsText,  eventNames;
    private int events;
    
    private OrderedGroup TGBox;
    private ArrayList<Node> buttons;
    private ImageButton2D hotButton;

    private static final Color3f colorIdle=new Color3f(0.6f,0.6f,0.6f),
            colorHot=new Color3f(0.9f,0.9f,0.5f),
            colorAction=new Color3f(0.95f,0.5f,0.95f),
            colorWhite=new Color3f(1f,1f,1f);
    
    
    public MessageBox(IModeController myController, IModeController receiver,
            String title, String contect,
            String[] buttonsText, String[] eventNames) {
        this.title = title;
        this.contect = contect;
        this.buttonsText = buttonsText;
        this.eventNames = eventNames;
        if (eventNames.length == buttonsText.length) {
            this.events = eventNames.length;
        } else {
            System.err.println("Illegal events Number");
        }
        this.setCapability(BranchGroup.ALLOW_DETACH);
        this.myController = myController;
        this.receiver = receiver;
        initMessageBox();
        this.addChild(TGBox);
    }
    
    public void setReceiver(IModeController myController, IModeController receiver){
        this.myController = myController;
        this.receiver = receiver;
        for(int itemID=2; itemID<buttons.size();itemID++){
            if(!buttons.get(itemID).equals(hotButton)){
                ((Pickable)buttons.get(itemID)).setStatue(Pickable.Idle);
            }else
                ((Pickable)buttons.get(itemID)).setStatue(Pickable.Hot);
        }
    }

    public int addSubItem(Pickable button) {
        button.setHost(this);
        buttons.add((ImageButton2D) button);
        TGBox.addChild((TransformGroup) button);
        hotButton = (ImageButton2D)this.buttons.get(2);
        hotButton.setStatue(Pickable.Hot);
        return buttons.size();
    }
    
    public int addSubItem(Node button) {
        buttons.add((Node) button);
        TGBox.addChild(button);
        return buttons.size();
    }
    
    public Object doEvent(String eventName, Object Param) {
        if (statue!=STATUE_FIXED) return null;
        if (eventName.equals("SetHotItem")){
            refreshCurrentItem((Pickable)Param);
            return null;
        }else{
            currentEvent=eventName;
            statue=STATUE_OUT;
            return null;
        }
    }

    private void nextItem(){
        int nextItemID=(buttons.indexOf(hotButton)+1)%buttons.size();
        if (nextItemID<2) nextItemID=2;
        refreshCurrentItem((Pickable)buttons.get(nextItemID));
    }
    private void preItem(){
        int nextItemID=(buttons.indexOf(hotButton)-1);
        if (nextItemID<2) nextItemID=buttons.size()-1;
        refreshCurrentItem((Pickable)buttons.get(nextItemID));
    }
    
    private void refreshCurrentItem(Pickable currentItem){
        if(this.hotButton.equals(currentItem)) return;    //仅当变化发生时更新
        hotButton=(ImageButton2D)currentItem;
        for(int itemID=2; itemID<buttons.size();itemID++){
            if(!buttons.get(itemID).equals(currentItem)){
                ((Pickable)buttons.get(itemID)).setStatue(Pickable.Idle);
            }else
                ((Pickable)buttons.get(itemID)).setStatue(Pickable.Hot);
        }
    }
    public void processKeyEvent(KeyEvent evt) {
        if (evt.getID()==KeyEvent.KEY_RELEASED){
            switch(evt.getKeyCode()){
                case KeyEvent.VK_UP:
                    preItem();
                    break;
                case KeyEvent.VK_DOWN:
                    nextItem();
                    break;
                case KeyEvent.VK_ENTER:
                    hotButton.setStatue(Pickable.Action);
                    break;
                case KeyEvent.VK_ESCAPE:
                    doEvent("Cancel",null);
                    break;
            }
        }
    }

    public void invoke(double Step) {
        switch(statue){
            case STATUE_IN:{
                step+=1.2*Step;
                if (step>=1) {
                    statue=STATUE_FIXED;
                    step=1;
                }
                setImageStatue();
                break;
            }
            case STATUE_OUT:{
                step+=2*Step;
                if (step>=2) {
                    statue=STATUE_IN;
                    step=0;
                    myController.doEvent(currentEvent,null);
                }
                setImageStatue();
                break;
            }
        }
    }
    private void setImageStatue(){
        double top=0.03*buttons.size();
        double sinStep=Math.pow(step-1, 3)+1;
        for (int buttonId=0; buttonId<buttons.size(); buttonId++){
            Node target=buttons.get(buttonId);
            double targetY=(1-sinStep)*0.3+(top-0.06*buttonId);
            Transform3D t3d=new Transform3D(),r3d=new Transform3D();
            t3d.set(new Vector3d(-0.2*targetY,targetY,-1));
            if (sinStep<1)
                r3d.rotZ(Math.PI*0.5-Math.PI*0.5*sinStep);
            else
                r3d.rotY(Math.PI*0.5-Math.PI*0.5*sinStep);
                
            t3d.mul(r3d);
            ((TransformGroup)target).setTransform(t3d);
        }
    }
    
    private void initMessageBox(){
        TGBox=new OrderedGroup();
        /*background=new ImageButton2D(new Vector3d(0,0,-1),
                0.3f, 1f, "Image.MessageBox.Back",
                colorWhite, colorWhite, colorWhite, "CloseMsgBox");
        background.setEnable(false);
        background.setHost(this);*/
        
        TGBox.addChild(ObjectFactory.createTexturedSurface(2.5f, 1.875f, -3f,      //背景遮蔽
                colorWhite, 0f, PathRes.getPath("Image.MessageBox.Black"),
                false  , false));
        //TGBox.addChild(background);                                             //轨道背景
        
        
        buttons=new ArrayList<Node>();
        addSubItem(getTG(ObjectFactory.createTexturedSurface(0.30f, 0.04f, 0f,       //标题
                colorWhite, 0f, makeTextTexture(title,512,48,Font.BOLD),
                false  , false),0f,0.2f,0f));
        addSubItem(getTG(ObjectFactory.createTexturedSurface(0.30f, 0.04f, 0f,       //正文
                colorWhite, 0f, makeTextTexture(contect,512,36,Font.PLAIN),
                false  , false),0f,0.13f,0f));
        
        for (int buttonId=0; buttonId<this.buttonsText.length; buttonId++){
            addSubItem((Pickable)(new ImageButton2D(
                    new Vector3d(0,0.06-0.07*buttonId,0), 0.30f, 0.04f, 
                    makeTextTexture(buttonsText[buttonId],512,42,Font.PLAIN),
            colorIdle, colorHot, colorAction, eventNames[buttonId])));
        }
        
    }
    private Texture2D makeTextTexture(String Title, int width,int fontsize, int fonttype) {
        BufferedImage tabBuffer = new BufferedImage(width, 64, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) tabBuffer.getGraphics();
        g2d.setColor(new Color(0, 0, 0, 128));
        g2d.fillRect(0, 0, width, 64);
        g2d.setFont(new Font("微软雅黑", fonttype, fontsize));
        g2d.setColor(new Color(255, 255, 255));
        g2d.drawString(Title, 0, 48);
        ImageComponent2D ic2D = new ImageComponent2D(ImageComponent.FORMAT_RGBA, tabBuffer, true, false);
        Texture2D textureOut = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA, width, 64);
        textureOut.setImage(0, ic2D);
        return textureOut;
    }
    private static TransformGroup getTG(Node child, float x, float y, float z) {
        Transform3D transRes = new Transform3D();
        transRes.set(new Vector3f(x, y, z));
        TransformGroup TGRes = new TransformGroup(transRes);
        TGRes.setCapability(TGRes.ALLOW_TRANSFORM_WRITE);
        if (child != null) {
            TGRes.addChild(child);
        }
        return TGRes;
    }
    
}
